﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects.DataClasses;
using System.Data;
using System.Data.Objects;
using System.Linq.Expressions;
using System.Runtime.Caching;

namespace IRC.IRepairClouds.DataLayer.Cache
{
    public class EntityCacheManager : CacheManager<EntityObject>
    {
        protected override string CacheManagerName
        {
            get { return "Entity Cache Manager"; }
        }

        protected override string Group
        {
            get { return "Entity"; }
        }

        protected override IEnumerable<CachedKeys> GetCachedKeys(EntityObject obj)
        {
            yield return new CachedKeys(obj.EntityKey.GetCacheKey());
        }

        private T Create<T>(ICloudRepairEntities dbContext, EntityKey entityKey) where T : EntityObject
        {
            entityKey.ThrowIfNull("entityKey");

            ICloudRepairEntities db = dbContext;
            bool disposeDB = false;
            if (db == null) {
                db = new ICloudRepairEntities();
                disposeDB = true;
            }
            try {
                object found;
                if (!db.TryGetObjectByKey(entityKey, out found))
                    throw new NotFoundException().Process(e => {
                        e.Data["entityKey"] = entityKey.JSON_BaseSerializeEx();
                    });
                T res = (T)found;
                db.Detach(res);
                return res;
            }
            finally {
                if (disposeDB)
                    db.Dispose();
            }
        }

        public T Get<T>(EntityKey entityKey) where T : EntityObject
        {
            return Get<T>(null, entityKey);
        }

        public T Get<T>(ICloudRepairEntities dbContext, EntityKey entityKey) where T : EntityObject
        {
            try {
                var e = (T)GetBase(() => Create<T>(dbContext, entityKey), new object[] { entityKey.GetCacheKey() });
                if (e != null)
                    return e.CreateCopy();
                return null;
            }
            catch (NotFoundException) {
                throw;
            }
            catch (Exception ex) {
                ex.Data["entityKey"] = entityKey.JSON_BaseSerializeEx();
                throw;
            }
        }
    }
}
